In modern execution environments, a program generally only has control of its own private virtual memory and the unprivileged state of the central processing unit (CPU) executing the program. To alter the state of the system at large, the program must request that the operating system (OS) perform some operation on its behalf, almost always by calling a well-defined API function provided by the OS. Capturing the API calls performed by a program, and additionally the parameters supplied in each call and the result of each call, is a simple, concise, and effective means of profiling the behavior of a program.
Most API call profiling systems execute a program of interest in a virtual machine featuring a complete OS installation and some amount of user- or kernel-mode instrumentation for intercepting and recording API calls. However, such a dynamic analysis approach consumes a significant amount of resources required for each virtual machine, thereby dramatically limiting the number of virtual machines that can concurrently run on a physical computer. In addition, programs are typically executed in real-time and so they might wait for some event to occur or time interval to elapse before exhibiting any significant activity—meaning the system might be forced to run each program of interest for minutes or risk aborting before the program has performed substantive API calls.
Lighter-weight implementations that emulate programs of interest have been adopted. However, emulators often suffer from incomplete implementations of the API and detectable divergences from the behavior of a real execution environment, but they generally offer size and speed benefits. Both emulators and virtual machines face the significant drawback that they can only profile a single path of execution—generally they do not consider the other paths which execution potentially could have followed through the code.